/*
* @(#)AlertManager.java
*
* Copyright (c) 2003 DCIVision Ltd
* All rights reserved.
*
* This software is the confidential and proprietary information of DCIVision
* Ltd ("Confidential Information").  You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the license
* agreement you entered into with DCIVision Ltd.
 */

package com.dcivision.alert.core;

import java.sql.Connection;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.LogFactoryImpl;

import com.dcivision.alert.bean.MtmUpdateAlertRecipient;
import com.dcivision.alert.bean.UpdateAlert;
import com.dcivision.alert.bean.UpdateAlertLogAction;
import com.dcivision.alert.bean.UpdateAlertSystemLog;
import com.dcivision.alert.bean.UpdateAlertType;
import com.dcivision.alert.dao.MtmUpdateAlertRecipientDAObject;
import com.dcivision.alert.dao.UpdateAlertDAObject;
import com.dcivision.alert.dao.UpdateAlertLogActionDAObject;
import com.dcivision.alert.dao.UpdateAlertSystemLogDAObject;
import com.dcivision.alert.dao.UpdateAlertTypeDAObject;
import com.dcivision.alert.web.ListSystemMessageForm;
import com.dcivision.calendar.bean.CalendarRecord;
import com.dcivision.calendar.dao.CalendarRecordDAObject;
import com.dcivision.contact.bean.ContactPerson;
import com.dcivision.contact.dao.ContactPersonDAObject;
import com.dcivision.dms.bean.DmsDocument;
import com.dcivision.dms.core.DocumentOperationManager;
import com.dcivision.dms.core.DocumentRetrievalManager;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ApplicationExceptionList;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.MessageResourcesFactory;
import com.dcivision.framework.PermissionManager;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.bean.AbstractBaseObject;
import com.dcivision.framework.web.AbstractSearchForm;
import com.dcivision.user.bean.UserRecord;
import com.dcivision.user.dao.MtmUserRecordUserGroupDAObject;
import com.dcivision.user.dao.MtmUserRecordUserRoleDAObject;
import com.dcivision.user.dao.UserRecordDAObject;

/**
  AlertManager.java

  This class is the AlertManager.

    @author           Scott Tong
    @company          DCIVision Limited
    @creation date    22/08/2003
    @version          $Revision: 1.117.2.2 $
    */
/* ********************************Modify History***********************************************
 * Modify by  : Jicle.Wang 
 * Modify date: 2006/08/31
 * BugID      : 6051
 * Description: 'Due Date' and 'Message' are lost when document be invitated more than noce.
 * *********************************************************************************************
 */
public class AlertManager {

  public static final String REVISION = "$Revision: 1.117.2.2 $";

  protected Log logger = new LogFactoryImpl().getInstance(this.getClass());

  private SessionContainer sessionContainer;
  private Connection conn;

  public AlertManager(Connection dbConn) {
    this.sessionContainer = new SessionContainer();
    this.conn = dbConn;
  }

  public AlertManager(SessionContainer sessionContainer, Connection conn) {
    this.sessionContainer = sessionContainer;
    this.conn = conn;
  }

  public void release() {
    this.sessionContainer = null;
    this.conn = null;
  }

  public void createAlertTypesRecipientsNLogs(UpdateAlert updateAlert, UpdateAlertType[] updateTypes, Integer versionID, MtmUpdateAlertRecipient[] recipientObjects) throws ApplicationException {
    this.createAlertTypesRecipientsNLogs(updateAlert, updateTypes, versionID, recipientObjects,null);
  }

  public void createAlertTypesRecipientsNLogs(UpdateAlert updateAlert, UpdateAlertType[] updateTypes, Integer versionID, MtmUpdateAlertRecipient[] recipientObjects,List alertTypeList) throws ApplicationException {
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    MtmUpdateAlertRecipientDAObject alertRecipientDAO = new MtmUpdateAlertRecipientDAObject(sessionContainer, conn);
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);

    for (int i = 0; i < updateTypes.length; i++) {
      UpdateAlertType updateAlertType = updateTypes[i];
      updateAlertType.setUpdateAlertID(updateAlert.getID());
      updateAlertType = (UpdateAlertType) updateTypeDAO.insertObject(updateAlertType);

      if (UpdateAlert.INVITE_ACTION.equals(updateAlertType.getActionType())) {
        UpdateAlertSystemLog alertSystemLog = new UpdateAlertSystemLog();
        alertSystemLog.setActionUserID(sessionContainer.getUserRecordID());
        alertSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
        alertSystemLog.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
        alertSystemLog.setVersionID(versionID);
        alertSystemLog = (UpdateAlertSystemLog) alertSystemDAO.insertObject(alertSystemLog);
      }else if(!updateAlert.getClearLogs()){
      	
      	List alertSystemLogList = null;
      	if (!Utility.isEmpty(alertTypeList)){
      		for (int m = 0; m < alertTypeList.size(); m++){
      			UpdateAlertType alertType = (UpdateAlertType)alertTypeList.get(m);
      			if (Utility.isEmpty(alertType.getActionType())) continue;
      			if (alertType.getActionType().equals(updateAlertType.getActionType())){
      				alertSystemLogList = this.getListOldAlertSystemLog(alertType,updateAlertType.getActionType());
      				if (!Utility.isEmpty(alertSystemLogList)){
      					for (int n = 0; n < alertSystemLogList.size(); n++){
      						UpdateAlertSystemLog alertSystemLog = (UpdateAlertSystemLog)alertSystemLogList.get(n);
            			alertSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
            			alertSystemLog=(UpdateAlertSystemLog)alertSystemDAO.updateObject(alertSystemLog); 
      					}
      				}
      			}
      		}
      	}
      	
//        UpdateAlertSystemLog alertSystemLog = null;
//        if(!Utility.isEmpty(alertTypeList)){
//          alertSystemLog=this.getOldAlertSystemLog(alertTypeList,updateAlertType.getActionType());
//        }
//        if(!Utility.isEmpty(alertSystemLog)){
//          alertSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
//          alertSystemLog=(UpdateAlertSystemLog)alertSystemDAO.updateObject(alertSystemLog); 
//        }               
      }

      for (int j = 0; j < recipientObjects.length; j++) {
        MtmUpdateAlertRecipient updateRecipient = new MtmUpdateAlertRecipient();
        updateRecipient.setRecipientType(recipientObjects[j].getRecipientType());
        updateRecipient.setRecipientID(recipientObjects[j].getRecipientID());
        updateRecipient.setUpdateAlertID(updateAlert.getID());
        updateRecipient.setUpdateAlertTypeID(updateAlertType.getID());
        alertRecipientDAO.insertObject(updateRecipient);
      }
    }
    updateTypeDAO=null;
    alertRecipientDAO=null;
    alertSystemDAO=null;
  }

  public UpdateAlert createUpdateAlert(UpdateAlert updateAlert, UpdateAlertType[] updateTypes, Integer versionID, MtmUpdateAlertRecipient[] recipientObjects) throws ApplicationException {
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);

   //check main update alert record exists for new creation
    UpdateAlert newupdateAlert = (UpdateAlert) updateAlertDAO.getByObjectTypeObjectID(GlobalConstant.OBJECT_TYPE_DOCUMENT, updateAlert.getObjectID());
    if (newupdateAlert == null) {
      newupdateAlert = (UpdateAlert) updateAlertDAO.insertObject(updateAlert);
    }
    createAlertTypesRecipientsNLogs(newupdateAlert, updateTypes, versionID, recipientObjects);
    updateAlertDAO=null;
    return newupdateAlert;
  }

  public void createInviteTypesRecipientsNLogs(UpdateAlert updateAlert, UpdateAlertType[] updateTypes, MtmUpdateAlertRecipient[] updateRecipient, Integer versionID, String objectName, Timestamp refDate, String eventName, Integer creatorID, List notifyUserIDList) throws ApplicationException {
    NotificationAdapter na = new NotificationAdapter(sessionContainer, conn);
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    MtmUpdateAlertRecipientDAObject alertRecipientDAO = new MtmUpdateAlertRecipientDAObject(sessionContainer, conn);
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    ApplicationExceptionList exceptionList = new ApplicationExceptionList();

    try{
      for (int i = 0; i < updateTypes.length; i++) {
        UpdateAlertType updateAlertType = updateTypes[i];
        boolean isWorkflowNotifyType = UpdateAlert.NOTIFY_TASK_COMPLETED_ACTION.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_ARRIVED_ACTION.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_OWNER_OVERDUE_ACTION.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_ALL_OVERDUE_ACTION.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_STOP_TRACK.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_BEFORE_DUE_DATE.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_IN_PROGRESSING.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_PENDING_FOR.equals(updateAlertType.getActionType())
        || UpdateAlert.DELEGATION_ACTION.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_DELEGATION_USER.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_PRIORITY_CHANGED.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_CHECK_OUT_BY_USER.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_COMPLETED_BY_USER.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_APPROVED.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_REJECT.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_YES.equals(updateAlertType.getActionType())
        || UpdateAlert.NOTIFY_TASK_NO.equals(updateAlertType.getActionType())
        || updateAlertType.getActionType().indexOf(UpdateAlert.NOTIFY_TASK_DECISION)==0;
        updateAlertType.setUpdateAlertID(updateAlert.getID());
        updateAlertType.setAlertSubject(updateAlertType.getAlertSubject());
        updateAlertType = (UpdateAlertType) updateTypeDAO.insertObject(updateAlertType);

        for (int r = 0; r < updateRecipient.length; r++) {
          MtmUpdateAlertRecipient recipient = updateRecipient[r];
          recipient.setUpdateAlertID(updateAlert.getID());
          recipient.setUpdateAlertTypeID(updateAlertType.getID());
          alertRecipientDAO.insertObject(recipient);
        }

        StringTokenizer stoken = new StringTokenizer(updateAlertType.getNotifyWay(), ",");
        List notifyChannelList = new ArrayList();
        while (stoken.hasMoreElements()) {
          notifyChannelList.add(stoken.nextElement());
        }
        java.util.Collections.sort(notifyChannelList);
        Integer systemLogID = null;
        for(int k=notifyChannelList.size();k>0;k--){
          //String actionType = (String) stoken.nextElement();
          String actionType = (String)notifyChannelList.get(k-1);
          if (UpdateAlert.EMAIL_NOTIFICATION.equals(actionType)) {
            //Active the Email Alert
            try {
              na.notifyByEmailInvite(updateAlert.getObjectType(),
                                     updateAlert.getObjectID(),
                                     updateAlertType.getActionType(), updateAlert,
                                     updateRecipient, objectName, refDate,
                                     eventName, creatorID, notifyUserIDList,null, systemLogID);
            } catch (ApplicationException appEx) { // in case cannot send email and exception is thrown 
              logger.info("Cannot send invitation email.");
              exceptionList.addException(appEx);
            }

            if (updateAlertType.getNotifyWay().indexOf(UpdateAlert.SYSTEM_NOTIFICATION) < 0) {
              if (isWorkflowNotifyType) {
                //Active the System Log
                UpdateAlertSystemLog alertSystemLog = new UpdateAlertSystemLog();
                alertSystemLog.setActionUserID(sessionContainer.getUserRecordID());
                alertSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
                alertSystemLog.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
                alertSystemLog.setVersionID(versionID);
                alertSystemLog = (UpdateAlertSystemLog) alertSystemDAO.insertObject(alertSystemLog);
               
              }
            }
          }
          else if (UpdateAlert.SYSTEM_NOTIFICATION.equals(actionType)) {
            if (UpdateAlert.INVITE_ACTION.equals(updateAlertType.getActionType())
                || UpdateAlert.DISCUSS_ACTION.equals(updateAlertType.getActionType())
                    || isWorkflowNotifyType                   
               ) {
              //Active the System Log
              UpdateAlertSystemLog alertSystemLog = new UpdateAlertSystemLog();
              alertSystemLog.setActionUserID(sessionContainer.getUserRecordID());
              alertSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
              alertSystemLog.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
              alertSystemLog.setActionDate(refDate);
              alertSystemLog.setVersionID(versionID);
              alertSystemLog = (UpdateAlertSystemLog) alertSystemDAO.insertObject(alertSystemLog);
              
              if(alertSystemLog!=null){
                systemLogID = alertSystemLog.getID();      
              }
            }
          }
        }
      }
      conn.commit();
      updateTypeDAO = null;
      alertRecipientDAO = null;
      alertSystemDAO = null;
      na.release();
      //exceptionList.throwException();
    } catch (ApplicationException appEx) {
      logger.error(appEx, appEx);
    } catch (Exception e) {
      logger.error(e, e);
    }
  }

  public void createWorkflowEmailNotification(Integer objectID, String objectType, String actionType, List notifyUserIDList) throws ApplicationException {
    try{        
      logger.debug("create Workflow email notification");
      NotificationAdapter na = new NotificationAdapter(sessionContainer, conn);
      na.notifyByEmailInvite(objectType, objectID, actionType, null, null, null, null, null, new Integer(-1), notifyUserIDList, true);
      na.release();
    } catch (ApplicationException appEx) {
      logger.error(appEx, appEx);
      //throw appEx;
    } catch (Exception e) {
      logger.error(e, e);
    }
  }
  
  public void createWorkflowEmailNotification(Integer objectID, String objectType, String actionType, List notifyUserIDList, Integer notifyAtMat, Integer notifyAtFiled, Integer actionID) throws ApplicationException {
      try{      
        logger.debug("create Workflow email notification");
        NotificationAdapter na = new NotificationAdapter(sessionContainer, conn);
        if (!Utility.isEmpty(notifyAtMat) && !Utility.isEmpty(notifyAtFiled)) {
          na.notifyByEmailInvite(objectType, objectID, actionType, null, null, notifyAtMat.toString(), null, notifyAtFiled.toString(), actionID, notifyUserIDList, true);
        } else {
          na.notifyByEmailInvite(objectType, objectID, actionType, null, null, null, null, null, actionID, notifyUserIDList, true);   
        }
        na.release();
      } catch (ApplicationException appEx) {
        logger.error(appEx, appEx);
        throw appEx;//simon_add
      } catch (Exception e) {
        logger.error(e, e);
      }
    }

  public UpdateAlert createUpdateAlert(UpdateAlert updateAlert, UpdateAlertType[] updateTypes, MtmUpdateAlertRecipient[] updateRecipient, Integer versionID, String objectName, Timestamp refDate, String eventName, Integer creatorID, List notifyUserIDList) throws ApplicationException {
    //check main update alert record exists for new creation
    UpdateAlert newupdateAlert = new UpdateAlert();
    try{
      UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
      
      /* Jicle.Wang 6051 2006/08/31 Start */
      //newupdateAlert = (UpdateAlert) updateAlertDAO.getByObjectTypeObjectID(GlobalConstant.OBJECT_TYPE_DOCUMENT, updateAlert.getObjectID());
      newupdateAlert = (UpdateAlert) updateAlertDAO.getByUserID(updateAlert.getObjectType(), sessionContainer.getUserRecordID(), updateAlert.getObjectID());
      /* Jicle.Wang 6051 2006/08/31 End   */ 
      if (newupdateAlert == null) {
        newupdateAlert = (UpdateAlert) updateAlertDAO.insertObject(updateAlert);
      }

      createInviteTypesRecipientsNLogs(newupdateAlert, updateTypes, updateRecipient, versionID, objectName, refDate, eventName, creatorID, notifyUserIDList);
      updateAlertDAO = null;
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      logger.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
    }
    return newupdateAlert;
  }

  public UpdateAlert updateUpdateAlert(UpdateAlert updateAlert, UpdateAlertType[] updateTypes, Integer versionID, MtmUpdateAlertRecipient[] recipientObjects) throws ApplicationException {
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    UpdateAlert newUpdateAlert= new UpdateAlert();  
    List alertTypeList = updateTypeDAO.getByUpdateAlertIDByOwnerID(updateAlert.getID(), null, sessionContainer.getUserRecordID());
    try {
      newUpdateAlert = (UpdateAlert) updateAlertDAO.updateObject(updateAlert);
      this.deleteUpdateAlert(updateAlert, false);

      //Create new alert types and recipients
      createAlertTypesRecipientsNLogs(newUpdateAlert, updateTypes, versionID, recipientObjects,alertTypeList);
      updateAlertDAO = null;
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      logger.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
    }
    return newUpdateAlert;
  }

  public UpdateAlert updateUpdateAlert(UpdateAlert updateAlert, UpdateAlertType[] updateTypes, MtmUpdateAlertRecipient[] updateRecipient, Integer versionID, String objectName, Timestamp refDate, String eventName, Integer creatorID, List notifyUserIDList) throws ApplicationException {
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);

    UpdateAlert newUpdateAlert = new UpdateAlert();
    try {
      newUpdateAlert = (UpdateAlert) updateAlertDAO.updateObject(updateAlert);
      deleteUpdateAlert(updateAlert, false);
      createInviteTypesRecipientsNLogs(updateAlert, updateTypes, updateRecipient, versionID, objectName, refDate, eventName, creatorID, notifyUserIDList);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      logger.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
    }
    return newUpdateAlert;
  }

  public void deleteUpdateAlert(UpdateAlert updateAlert) throws ApplicationException {
    deleteUpdateAlert(updateAlert, true);
  }



/** 
 * any update of the deleteUpdateAlert, also need to update the hardDeleteUpdateAlert,
 * in order to syn the logic
 * 
 * */
  public void deleteUpdateAlert(UpdateAlert updateAlert, boolean bDelUpdateAlert) throws ApplicationException {
    List delList = new ArrayList();
    List alertInviteList = new ArrayList();
    List alertTypeList = new ArrayList();
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
MtmUpdateAlertRecipientDAObject alertRecipientDAO = new MtmUpdateAlertRecipientDAObject(sessionContainer, conn);
UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);

try{
      //get dele lis using current user id
      alertInviteList = updateTypeDAO.getByUpdateAlertIDByOwnerID(updateAlert.getID(), UpdateAlert.INVITE_TYPE, sessionContainer.getUserRecordID());
      alertTypeList = updateTypeDAO.getByUpdateAlertIDByOwnerID(updateAlert.getID(), null, sessionContainer.getUserRecordID());
      if (!Utility.isEmpty(updateAlert.getAlertType())) {
        if (UpdateAlert.INVITE_TYPE.equals(updateAlert.getAlertType())) {
          delList = alertInviteList;
        } else if (UpdateAlert.ALERT_TYPE.equals(updateAlert.getAlertType())) {
          delList = alertTypeList;
        }
        //delete the recipient; system log; and alert type
        for (int i = 0; i < delList.size(); i++) {
          UpdateAlertType updateAlertType = (UpdateAlertType) delList.get(i);
          //alertRecipientDAO.deleteByUpdateAlertTypeID(updateAlertType.getID()); // EIP-1174 07/01/08 LEE REMOVE
          if (updateAlert.getClearLogs()) {
            alertRecipientDAO.deleteByUpdateAlertTypeID(updateAlertType.getID()); // EIP-1174 07/01/08 LEE ADD
            alertSystemDAO.deleteByUpdateAlertTypeID(updateAlertType);
          }
          updateTypeDAO.deleteObjectByID(updateAlertType.getID());
        }
      } else { //Clear all alertType
        //delete the recipient; system log; and alert type
        for (int i = 0; i < alertInviteList.size(); i++) {
          UpdateAlertType updateAlertType = (UpdateAlertType) alertInviteList.get(i);
          alertRecipientDAO.deleteByUpdateAlertTypeID(updateAlertType.getID());
          alertSystemDAO.deleteByUpdateAlertTypeID(updateAlertType);
          updateTypeDAO.deleteObjectByID(updateAlertType.getID());
        }
        for (int i = 0; i < alertTypeList.size(); i++) {
          UpdateAlertType updateAlertType = (UpdateAlertType) alertTypeList.get(i);
          alertRecipientDAO.deleteByUpdateAlertTypeID(updateAlertType.getID());
          alertSystemDAO.deleteByUpdateAlertTypeID(updateAlertType);
          updateTypeDAO.deleteObjectByID(updateAlertType.getID());
        }

      }

      //Del existing types for alert if no other type existed
      if (bDelUpdateAlert) {
        //get all other list
        List alertList = updateTypeDAO.getByUpdateAlertIDByOwnerID(updateAlert.getID(), "ALL", null);
        if (UpdateAlert.INVITE_TYPE.equals(updateAlert.getAlertType())) {
          if (Utility.isEmpty(alertList)) {
              updateAlertDAO.deleteObject(updateAlert);
              DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
              // update record in DMS_DOCUMENT
              docOperationManager.setAlertInviteID(updateAlert.getObjectID(), null);
          }
        } else if (UpdateAlert.ALERT_TYPE.equals(updateAlert.getAlertType())) {
          if (Utility.isEmpty(alertList)) {
            if (updateAlert.getClearLogs()) { // EIP-1174 07/01/08 LEE
              updateAlertDAO.deleteObject(updateAlert);
              DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
              // update record in DMS_DOCUMENT
              docOperationManager.setAlertEditID(updateAlert.getObjectID(), null);
            }
          }
        } else { //Clear all update Alert
          updateAlertDAO.deleteObject(updateAlert);
        }
      }
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      logger.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
    }
  }
  
  public void hardDeleteUpdateAlert(UpdateAlert updateAlert, boolean bDelUpdateAlert) throws ApplicationException {
    List delList = new ArrayList();
    List alertInviteList = new ArrayList();
    List alertTypeList = new ArrayList();
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    MtmUpdateAlertRecipientDAObject alertRecipientDAO = new MtmUpdateAlertRecipientDAObject(sessionContainer, conn);
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    
    try{
      //get dele lis using current user id
      alertInviteList = updateTypeDAO.getInactiveByUpdateAlertIDByOwnerID(updateAlert.getID(), UpdateAlert.INVITE_TYPE, sessionContainer.getUserRecordID());
      alertTypeList = updateTypeDAO.getInactiveByUpdateAlertIDByOwnerID(updateAlert.getID(), null, sessionContainer.getUserRecordID());
      if (!Utility.isEmpty(updateAlert.getAlertType())) {
        if (UpdateAlert.INVITE_TYPE.equals(updateAlert.getAlertType())) {
          delList = alertInviteList;
        } else if (UpdateAlert.ALERT_TYPE.equals(updateAlert.getAlertType())) {
          delList = alertTypeList;
        }
        //delete the recipient; system log; and alert type
        for (int i = 0; i < delList.size(); i++) {
          UpdateAlertType updateAlertType = (UpdateAlertType) delList.get(i);
          alertRecipientDAO.deleteByUpdateAlertTypeID(updateAlertType.getID());
          if (updateAlert.getClearLogs()) {
            alertSystemDAO.deleteByUpdateAlertTypeID(updateAlertType);
          }
          updateTypeDAO.hardDeleteByID(updateAlertType.getID());
        }
      } else { //Clear all alertType
        //delete the recipient; system log; and alert type
        for (int i = 0; i < alertInviteList.size(); i++) {
          UpdateAlertType updateAlertType = (UpdateAlertType) alertInviteList.get(i);
          alertRecipientDAO.deleteByUpdateAlertTypeID(updateAlertType.getID());
          alertSystemDAO.deleteByUpdateAlertTypeID(updateAlertType);
          updateTypeDAO.hardDeleteByID(updateAlertType.getID());
        }
        for (int i = 0; i < alertTypeList.size(); i++) {
          UpdateAlertType updateAlertType = (UpdateAlertType) alertTypeList.get(i);
          alertRecipientDAO.deleteByUpdateAlertTypeID(updateAlertType.getID());
          alertSystemDAO.deleteByUpdateAlertTypeID(updateAlertType);
          updateTypeDAO.hardDeleteByID(updateAlertType.getID());
        }
        
      }
      
      //Del existing types for alert if no other type existed
      if (bDelUpdateAlert) {
        //get all other list
        List alertList = updateTypeDAO.getInactiveByUpdateAlertIDByOwnerID(updateAlert.getID(), "ALL", null);
        if (UpdateAlert.INVITE_TYPE.equals(updateAlert.getAlertType())) {
          if (Utility.isEmpty(alertList)) {
            updateAlertDAO.hardDelete(updateAlert);
            DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
            // update record in DMS_DOCUMENT
            docOperationManager.setAlertInviteID(updateAlert.getObjectID(), null);
          }
        } else if (UpdateAlert.ALERT_TYPE.equals(updateAlert.getAlertType())) {
          if (Utility.isEmpty(alertList)) {
            updateAlertDAO.hardDelete(updateAlert);
            DocumentOperationManager docOperationManager = new DocumentOperationManager(sessionContainer, conn);
            // update record in DMS_DOCUMENT
            docOperationManager.setAlertEditID(updateAlert.getObjectID(), null);
          }
        } else { //Clear all update Alert
          updateAlertDAO.hardDelete(updateAlert);
        }
      }
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      logger.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
    }
 }

  public UpdateAlertType createAlertUpdateType(UpdateAlertType dmsAlertUpdateType) throws ApplicationException {
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    UpdateAlertType updateAlertType = (UpdateAlertType)updateTypeDAO.insertObject(dmsAlertUpdateType);
    updateTypeDAO=null;
    return updateAlertType;
  }

  public UpdateAlert createUpdateAlert(UpdateAlert alert, String objectType) throws ApplicationException {
    //check main update alert record exists for new creation
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    UpdateAlert updateAlert = (UpdateAlert)updateAlertDAO.getByObjectTypeObjectID(objectType, alert.getObjectID());
    if (updateAlert==null) {
      updateAlert = (UpdateAlert) updateAlertDAO.insertObject(alert);
    }
    updateAlertDAO=null;
    return updateAlert;
  }

  public MtmUpdateAlertRecipient createUpdateAlertRecipient(UpdateAlert alert, UpdateAlertType alertType, MtmUpdateAlertRecipient recipient) throws ApplicationException {
    recipient.setUpdateAlertID(alert.getID());
    recipient.setUpdateAlertTypeID(alertType.getID());
    MtmUpdateAlertRecipientDAObject alertRecipientDAO = new MtmUpdateAlertRecipientDAObject(sessionContainer, conn);
    MtmUpdateAlertRecipient alertRecipient = (MtmUpdateAlertRecipient)alertRecipientDAO.insertObject(recipient);
    alertRecipientDAO=null;
    return alertRecipient;
  }

  public UpdateAlertSystemLog createSystemLog(UpdateAlertSystemLog updateAlertSystemLog) throws ApplicationException {
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    UpdateAlertSystemLog systemLog = (UpdateAlertSystemLog) alertSystemDAO.insertObject(updateAlertSystemLog);
    alertSystemDAO=null;;
    return systemLog;
  }

  public void createUpdateAlertSystemLog(Integer updateAlertID, Integer objectID, String replyType) throws ApplicationException {
    createUpdateAlertSystemLog(updateAlertID, objectID,replyType,null);
  }
  public void createUpdateAlertSystemLog(Integer updateAlertID, Integer objectID, String replyType,String message) throws ApplicationException {
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    MtmUpdateAlertRecipientDAObject alertRecipientDAO = new MtmUpdateAlertRecipientDAObject(sessionContainer, conn);
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    UpdateAlertType updateAlertType = (UpdateAlertType) updateTypeDAO.getIDByTypeUpdateAlertID(UpdateAlert.INVITE_ACTION, updateAlertID);
    UpdateAlertSystemLog updateSystemLog = new UpdateAlertSystemLog();
    //delete the existing log
    updateSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
    updateSystemLog.setActionUserID(sessionContainer.getUserRecordID());
    alertSystemDAO.deleteByReply(updateSystemLog);

    //create new log
    updateSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
    updateSystemLog.setActionReply(replyType);
    if(!Utility.isEmpty(message))
    {
      updateSystemLog.setMessage(message);
    }
    alertSystemDAO.insertObject(updateSystemLog);
    /*
     *  Update Code Start
     *  Author        Jim.Zhou
     *  Date          2006/06/05
     *  Bug           #3950
     */
    //alertSystemDAO.updateByReply(updateSystemLog);//taohuaqing 2006-3-28
    /*
     *  Update Code End
     */
    updateTypeDAO=null;
    alertRecipientDAO = null;
    alertSystemDAO = null;

  }
  public UpdateAlert getUpdateAlert(Integer updateAlertID) throws ApplicationException {
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    UpdateAlert  updateAlert = (UpdateAlert) updateAlertDAO.getObjectByID(updateAlertID);
    updateAlertDAO=null;
    return updateAlert;
  }

  public UpdateAlertType getUpdateAlertTypeByActionTypeUpdateAlertID(String alertAction, Integer updateAlertID) throws ApplicationException{
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    UpdateAlertType alertType = (UpdateAlertType) updateTypeDAO.getIDByTypeUpdateAlertID(alertAction, updateAlertID);
    updateTypeDAO=null;
    return alertType;

  }

  public List listUpdateAlertByAction(String actionType) throws ApplicationException {
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    List resultList = updateAlertDAO.getByActionType(actionType);
    updateAlertDAO = null;
    return resultList;

  }

  public List listUpdateAlertByObjectTypeObjectIDAndAction(String objectType, Integer objectID, String actionType) throws ApplicationException {
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    List resultList = updateAlertDAO.getByObjectTypeObjectIDAndActionType(objectType, objectID, actionType);
    updateAlertDAO = null;
    return resultList;
  }

  public List listAlertUpdateTypeByUpdateAlertID(Integer updateAlertID, String actionType) throws ApplicationException {
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    List resultList = updateTypeDAO.getByUpdateAlertIDByOwnerID(updateAlertID, actionType, sessionContainer.getUserRecordID());
    updateTypeDAO = null;
    return resultList;
  }


  public List listAlertUpdateTypeByUpdateAlertID(Integer updateAlertID) throws ApplicationException {
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    List resultList = updateTypeDAO.getByUpdateAlertIDByOwnerID(updateAlertID, sessionContainer.getUserRecordID());
    updateTypeDAO = null;
    return resultList;
  }

/*
    public List listUpdateAlertByItemAndRecipient(Integer itemID, Integer recipientID, String recipientType) throws ApplicationException {
        UpdateupdateAlertDAObject updateAlertDAO = new UpdateupdateAlertDAObject(sessionContainer, conn);
        return updateAlertDAO.getByItemIDAndRecipientIDAndType(itemID, recipientID, recipientType);
    }
*/
  public List listUpdateAlertByObjectTypeObjectID(String objectType, Integer objectID) throws ApplicationException {
   UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
   List resultList = updateAlertDAO.getByObjectTypeObjectIDList(objectType, objectID);
   updateAlertDAO=null;
   return resultList;

  }

  public UpdateAlert getUpdateAlertByObjectTypeObjectIDRecordStatus( String objectType, Integer objectID, String recordStatus) throws ApplicationException {
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    UpdateAlert updateAlert = (UpdateAlert) updateAlertDAO.getByObjectTypeObjectIDRecordStatus(objectType, objectID,recordStatus);
    updateAlertDAO = null;
    return updateAlert;
  }

  public UpdateAlert getUpdateAlertByObjectTypeObjectID( String objectType, Integer objectID) throws ApplicationException {
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    UpdateAlert updateAlert = (UpdateAlert) updateAlertDAO.getByObjectTypeObjectID(objectType, objectID);
    updateAlertDAO = null;
    return updateAlert;
  }
  
  public UpdateAlert getInactiveUpdateAlertByObjectTypeObjectID( String objectType, Integer objectID) throws ApplicationException {
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
        UpdateAlert updateAlert = (UpdateAlert) updateAlertDAO.getInactiveByObjectTypeObjectID(objectType, objectID);
        updateAlertDAO = null;
        return updateAlert;
  }

  public String[] listCreatorIDByUpdateAlertIDByOwnerID(Integer updateAlertID, String actionType, Integer curUserID)throws ApplicationException {
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    String[] ary =  updateTypeDAO.getCreatorIDByUpdateAlertIDByOwnerID(updateAlertID, actionType, curUserID);
    updateTypeDAO=null;
    return ary;
  }

  public void scheduleJobNotification(UpdateAlert updateAlert, UpdateAlertType updateAlertType, AbstractBaseObject obj, java.util.Date triggerTime, List alertUserIDList, Integer systemLogID, String expireDate) throws ApplicationException {

    String recordTitle = "";
    String userName = "";
    String actionType = "";
    String objectType = "";
    String objectName = "";
    String atOrBefore = "";
    String userID ="";
    String objectID ="";
    String logID = "";
    String reminderType = "";
    int reminderAmount = 0;
    String notificationWay = "";
    String alertObjectMessag = "";
    Timestamp targetSrcTime = null;

    org.quartz.SimpleTrigger trigger =null;
   // Date startTime = TriggerTime;

    try {
      logger.info("scheduledJobVec.size(): " );
      org.quartz.Scheduler sched = com.dcivision.framework.SchedulerFactory.getScheduler(); ;

      //get corresponding object type and object
      actionType = updateAlert.getAlertType();
      userID=obj.getCreatorID().toString();
      userName = obj.getCreatorName();
      objectType = updateAlert.getObjectType();
      objectID=obj.getID().toString();
      if (systemLogID!=null) {
        logID = systemLogID.toString();
      }

      if (UpdateAlert.CALENDAR_TYPE.equals(updateAlert.getObjectType()) ) {
        CalendarRecord calendarRecord = (CalendarRecord)((CalendarRecord)obj).clone();
       // alertType = "Calendar";
        //TODO: required update for Calendar module
        //reminderAmount =;
        //reminderType=;
        notificationWay = calendarRecord.getReminderType();
        recordTitle = calendarRecord.getTitle();
        objectName = calendarRecord.getTitle();
        targetSrcTime = calendarRecord.getDatetime();
      }else if (UpdateAlert.DOCUMENT_TYPE.equals(updateAlert.getObjectType()) ) {
        DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, conn);
        DmsDocument dmsDocument = (DmsDocument)((DmsDocument)obj).clone();
        String location ="";
        reminderAmount =dmsDocument.getReminderAmount().intValue();
        reminderType=dmsDocument.getReminderType();
        //notificationWay = dmsDocument.getReminderType();
        notificationWay = TextUtility.join(notificationWay, dmsDocument.getNotificationWay());
        recordTitle = "Document Management Reminder Notification";
        objectName = dmsDocument.getDocumentName();
        targetSrcTime = dmsDocument.getEffectiveEndDate();
        location = docRetrievalManager.getLocationPath(dmsDocument.getParentID());
        // write document expired message
        alertObjectMessag = MessageResourcesFactory.getMessage(sessionContainer.getSessionLocale(),"alert.message.dear")+" "+userName+",\n\n"+
        MessageResourcesFactory.getMessage(sessionContainer.getSessionLocale(),"alert.message.document_expired")+expireDate+":\n\n" +
        MessageResourcesFactory.getMessage(sessionContainer.getSessionLocale(),"dms.label.name_label_D")+": "+objectName+"\n" +
        MessageResourcesFactory.getMessage(sessionContainer.getSessionLocale(),"dms.label.location")+": "+location;        
      }

      logger.info("******** Adding schedule for Alert on = "+updateAlert.getObjectType()+ " object ID = " + updateAlert.getObjectID());

      org.quartz.JobDataMap dataMap = new org.quartz.JobDataMap();
      dataMap.put("alert Method", updateAlertType.getNotifyWay());
      String s="";
      UserRecordDAObject userRecordDAO = new UserRecordDAObject(sessionContainer, conn);
      UserRecord userRecord = new UserRecord();

      for (int i=0;i<alertUserIDList.size();i++) {
        userRecord = (UserRecord) userRecordDAO.getObjectByID((Integer)alertUserIDList.get(i));
        s+=(userRecord.getEmail()+" ; ");
      }
      userRecordDAO=null;

      dataMap.put("notificationWay", notificationWay);
      dataMap.put("alertEmail", s);
      dataMap.put("recordTitle", recordTitle);
      dataMap.put("userName", userName);
      dataMap.put("actionType", actionType);
      dataMap.put("objectType",objectType);
      dataMap.put("objectName", objectName);
      dataMap.put("targetSrcTime", TextUtility.formatTimestamp(targetSrcTime));
      dataMap.put("atOrBefore", atOrBefore);
      dataMap.put("objectID", objectID);
      dataMap.put("userID", userID);
      dataMap.put("logID", logID);
      dataMap.put("alertObjectMessag", alertObjectMessag);      
      org.quartz.JobDetail job = new org.quartz.JobDetail("Alert_"+objectType+"_"+updateAlert.getObjectID(), "ALERT_JOBGROUP", com.dcivision.alert.core.ScheduleExecuteDetail.class);
      job.setJobDataMap(dataMap);

      logger.info("******** Schedule date: " + triggerTime.toString());
      trigger = new org.quartz.SimpleTrigger("AlertTrigger_"+objectType+"_"+updateAlert.getObjectID(), "ALERT_GROUP", triggerTime, null,0,0);

      //, null, 0, 0);
      trigger.setMisfireInstruction(org.quartz.SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW);
      logger.info("******** Trigger created");
      logger.info(job.getFullName() + " will run at: " + trigger.getNextFireTime() + " & repeat: " + trigger.getRepeatCount() + "/" + trigger.getRepeatInterval());

      Date ft = sched.scheduleJob(job, trigger);
      //sched.scheduleJob(job, trigger);
      logger.info("******** Trigger created");
      //}
      sched = null;
      //this.scheduledJobVec.clear();
    } catch (Exception e) {
      logger.error("Error in Scheduler.", e);
      throw new ApplicationException(ErrorConstant.SYS_SCHEDULER_ERROR);
    }
  }

  public void delScheduleJobNotification(UpdateAlert updateAlert) throws ApplicationException{
    if (updateAlert == null) return ;
    String objectType = updateAlert.getObjectType();

    org.quartz.SimpleTrigger trigger =null;
    CalendarRecord calendarRecord = null;
    //Date startTime = TriggerTime;
    try {
      org.quartz.Scheduler sched = com.dcivision.framework.SchedulerFactory.getScheduler(); ;
      sched.deleteJob("Alert_"+objectType+"_"+updateAlert.getObjectID(),"ALERT_JOBGROUP");
      logger.info("******** Trigger deleted");
      //Date ft = sched.scheduleJob(job, trigger);
      //sched.scheduleJob(job, trigger);
      sched = null;
      //this.scheduledJobVec.clear();
    } catch (Exception e) {
      logger.error(e, e);
    }
  }
  
  public MtmUpdateAlertRecipient[] getRecipient(String[] userRecords, String[] userGroups, String[] userRoles) {
    return getRecipient(userRecords, userGroups, userRoles, null,null);
  }
  public MtmUpdateAlertRecipient[] getRecipient(String[] userRecords, String[] userGroups, String[] userRoles,
      String[] externalEmail,String[] contactList,String[] contactPersonList)  {
    int userRecordTtl = userRecords==null? 0:userRecords.length;
    int userGroupTtl = userGroups==null? 0:userGroups.length;
    int userRoleTtl = userRoles==null? 0:userRoles.length;
    int externalEmailTtl = externalEmail==null? 0:externalEmail.length;
    int contactListTt1= contactList==null? 0:contactList.length;
    int contactPersonTt1 = contactPersonList==null?0:contactPersonList.length;
    MtmUpdateAlertRecipient[] tmpRecipients = new MtmUpdateAlertRecipient[userRecordTtl + userGroupTtl + userRoleTtl+externalEmailTtl+contactListTt1+contactPersonTt1];
    int k=-1;
    if (userRecords!=null) {
      for (int i=0; i<userRecords.length; i++) {
        MtmUpdateAlertRecipient recipient = new MtmUpdateAlertRecipient();
        recipient.setRecipientType(UpdateAlert.USER_RECIPIENT);
        recipient.setRecipientID(TextUtility.parseIntegerObj(userRecords[i]));
        recipient.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
        tmpRecipients[++k]=recipient;
      }
    }
    if (userGroups!=null) {
      for (int i=0; i<userGroups.length; i++) {
        MtmUpdateAlertRecipient recipient = new MtmUpdateAlertRecipient();
        recipient.setRecipientType(UpdateAlert.GROUP_RECIPIENT);
        recipient.setRecipientID(TextUtility.parseIntegerObj(userGroups[i]));
        recipient.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
        tmpRecipients[++k]=recipient;
      }
    }
    if (userRoles!=null) {
      for (int i=0; i<userRoles.length; i++) {
        MtmUpdateAlertRecipient recipient = new MtmUpdateAlertRecipient();
        recipient.setRecipientType(UpdateAlert.ROLE_RECIPIENT);
        recipient.setRecipientID(TextUtility.parseIntegerObj(userRoles[i]));
        recipient.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
        tmpRecipients[++k]=recipient;
      }
    }
    if (externalEmail!=null) {
      for (int i=0; i<externalEmail.length; i++) {
        MtmUpdateAlertRecipient recipient = new MtmUpdateAlertRecipient();
        recipient.setRecipientType(UpdateAlert.EXTERNAL_EMAIL);
        recipient.setRecipientID(saveExtraEmail(externalEmail[i]));
        recipient.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
        tmpRecipients[++k]=recipient;
      }
    }
    if(contactList!=null){
      for(int i=0; i<contactList.length; i++){
        MtmUpdateAlertRecipient recipient = new MtmUpdateAlertRecipient();
        recipient.setRecipientType(UpdateAlert.CONTACT_RECIPIENT);
        recipient.setRecipientID(TextUtility.parseIntegerObj(contactList[i]));
        recipient.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
        tmpRecipients[++k]=recipient;
      }
    }
    if(contactPersonList!=null){
      for(int i=0; i<contactPersonList.length; i++){
        MtmUpdateAlertRecipient recipient = new MtmUpdateAlertRecipient();
        recipient.setRecipientType(UpdateAlert.CONTACT_PERSON);
        recipient.setRecipientID(TextUtility.parseIntegerObj(contactPersonList[i]));
        recipient.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
        tmpRecipients[++k]=recipient;
      }
    }
    return tmpRecipients;
  }
  private Integer saveExtraEmail(String extraRecipient) {
    ContactPersonDAObject contactPersonDAObject = new ContactPersonDAObject(sessionContainer,conn);
      ContactPerson contactPerson = new ContactPerson();
      
      contactPerson.setOwnerID(sessionContainer.getUserRecordID());
      contactPerson.setFirstName("");
      contactPerson.setLastName("");
      contactPerson.setPhoneNo("");
      contactPerson.setMobileNo("");
      contactPerson.setFaxNo("");
      contactPerson.setEmail(extraRecipient);
      contactPerson.setRemarks("");
      contactPerson.setTitle("");
      contactPerson.setDepartment("");
      contactPerson.setPublicFlag("N");
      try {
        contactPerson=(ContactPerson)contactPersonDAObject.insertObject(contactPerson);
      }
      catch (ApplicationException e) {
        logger.error(e, e);
      }
      return contactPerson.getID();
  }
  public MtmUpdateAlertRecipient[] getRecipient(String[] userRecords, String[] userGroups, String[] userRoles,
      String[] contactList,String[] contactPersonList) {
    return getRecipient(userRecords, userGroups, userRoles, null,contactList,contactPersonList);
  }

  public List getRelatedUpdateAlertIDListByUserID (Integer userID) throws ApplicationException {
    List validUpdateAlertIDList = new ArrayList();

    //get Update Alert System Log using the user id, role id and group id
    MtmUserRecordUserGroupDAObject mtmUserGroupDAO = new MtmUserRecordUserGroupDAObject(sessionContainer, conn);
    List userGroupList = mtmUserGroupDAO.getUserGroupListByUserRecordID(userID);
    MtmUserRecordUserRoleDAObject mtmUserRoleDAO = new MtmUserRecordUserRoleDAObject(sessionContainer, conn);
    List userRoleList = mtmUserRoleDAO.getUserRoleListByUserRecordID(userID);

    MtmUpdateAlertRecipientDAObject mtmAlertRecipient = new MtmUpdateAlertRecipientDAObject(sessionContainer, conn);
    validUpdateAlertIDList = mtmAlertRecipient.getUpdateAlertListByUserRecordIDGroupListRoleList(userID, userGroupList, userRoleList);

    mtmUserGroupDAO=null;
    mtmUserRoleDAO=null;
    return validUpdateAlertIDList;
  }

  public List getInvtatRelatedUpdateAlertIDListByUserID (Integer userID) throws ApplicationException {
    List validUpdateAlertIDList = new ArrayList();

    //get Update Alert System Log using the user id, role id and group id
    MtmUserRecordUserGroupDAObject mtmUserGroupDAO = new MtmUserRecordUserGroupDAObject(sessionContainer, conn);
    List userGroupList = mtmUserGroupDAO.getUserGroupListByUserRecordID(userID);
    MtmUserRecordUserRoleDAObject mtmUserRoleDAO = new MtmUserRecordUserRoleDAObject(sessionContainer, conn);
    List userRoleList = mtmUserRoleDAO.getUserRoleListByUserRecordID(userID);

    MtmUpdateAlertRecipientDAObject mtmAlertRecipient = new MtmUpdateAlertRecipientDAObject(sessionContainer, conn);
    validUpdateAlertIDList = mtmAlertRecipient.getUpdateAlertIDListByUserRecordIDGroupListRoleList(userID, userGroupList, userRoleList);

    mtmUserGroupDAO=null;
    mtmUserRoleDAO=null;
    return validUpdateAlertIDList;
  }  
  
  public List getUpdateAlertSystemLogListByUpdateAlertIDList (List updateAlertIDList, AbstractSearchForm searchForm) throws ApplicationException {
    List systemLogList = new ArrayList();
    if ( !Utility.isEmpty(updateAlertIDList)) {
      UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
      systemLogList = alertSystemDAO.getSystemLogList(updateAlertIDList, searchForm);
      alertSystemDAO=null;
    }
    return systemLogList;
  }

  public UpdateAlertSystemLog getSystemLogByUpdateAlertTypeIDActionUserID(Integer updateAlertTypeID, Integer userID) throws ApplicationException {
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    UpdateAlertSystemLog alertSystem = (UpdateAlertSystemLog) alertSystemDAO.getByUpdateAlertTypeIDActionUserID(updateAlertTypeID, userID);
    alertSystemDAO = null;
    return alertSystem;
  }

  public UpdateAlertSystemLog getSystemLogByUpdateAlertIDActionType(Integer updateAlertID, String actionType) throws ApplicationException {
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    UpdateAlertSystemLog alertSystem = (UpdateAlertSystemLog) alertSystemDAO.getSystemLogByUpdateAlertIDActionType(updateAlertID, actionType);
    alertSystemDAO = null;
    return alertSystem;
  }

  public UpdateAlertSystemLog updateSystemLog(UpdateAlertSystemLog alertSystemLog) throws ApplicationException {
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    UpdateAlertSystemLog alertSystem = (UpdateAlertSystemLog) alertSystemDAO.updateObject(alertSystemLog);
    alertSystemDAO = null;
    return alertSystem;
  }

  public UpdateAlertType updateUpdateAlertType(UpdateAlertType alertType) throws ApplicationException {
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    alertType = (UpdateAlertType) updateTypeDAO.updateObject(alertType);
    updateTypeDAO = null;
    return alertType;
  }

  //Get Update Alert Calendar ToDo List
  public List getUpdateAlertCalendarToList () throws ApplicationException {
    List systemLogList = new ArrayList();
    CalendarRecordDAObject calendarRecordDAO = new CalendarRecordDAObject(sessionContainer, conn);
    systemLogList = calendarRecordDAO.getListByDatePeriodAndEventTypeAndCalendarIDsAndStatus(
                sessionContainer.getUserRecordID(),null,null,
                        new String[]{CalendarRecord.EVENT_TYPE_CALENDAR_TODO,},null,GlobalConstant.FALSE,null);
    calendarRecordDAO=null;
    return systemLogList;
  }

  //Get Update Alert Calendar Event List
  public List getUpdateAlertCalendarEventList () throws ApplicationException {
    List systemLogList = new ArrayList();
    String currentDate = TextUtility.formatDate(new Date(),SystemParameterFactory.getSystemParameter(SystemParameterConstant.
            DATE_FORMAT));
    
    CalendarRecordDAObject calendarRecordDAO = new CalendarRecordDAObject(sessionContainer, conn);
    systemLogList = calendarRecordDAO.getListByDatePeriodAndEventTypeAndCalendarIDsAndStatus(
                sessionContainer.getUserRecordID(),Utility.parseDateStringToSystemDate(currentDate,SystemParameterFactory.getSystemParameter(SystemParameterConstant.
            DATE_FORMAT)),null,
                        new String[]{CalendarRecord.EVENT_TYPE_CALENDAR_EVENT},null,null,null);
    calendarRecordDAO=null;
    return systemLogList;
  }
  
  //Get Update Alert Calendar Meeting List
  public List getUpdateAlertCalendarMeetingList () throws ApplicationException {
    List systemLogList = new ArrayList();
    String currentDate = TextUtility.formatDate(new Date(),SystemParameterFactory.getSystemParameter(SystemParameterConstant.
            DATE_FORMAT));
    
    CalendarRecordDAObject calendarRecordDAO = new CalendarRecordDAObject(sessionContainer, conn);
    systemLogList = calendarRecordDAO.getListByDatePeriodAndEventTypeAndCalendarIDsAndStatus(
                sessionContainer.getUserRecordID(),Utility.parseDateStringToSystemDate(currentDate,SystemParameterFactory.getSystemParameter(SystemParameterConstant.
            DATE_FORMAT)),null,
                        new String[]{CalendarRecord.EVENT_TYPE_CALENDAR_MEETING,CalendarRecord.EVENT_TYPE_CALENDAR_EVENT},null,null,null);
    calendarRecordDAO=null;
    return systemLogList;
  }
  public List getSystemLogListByUserRecordID (Integer userID, AbstractSearchForm searchForm)throws ApplicationException {
    return getSystemLogListByUserRecordID(userID, searchForm,"no");
  }
  public List getSystemLogListByUserRecordID (Integer userID, AbstractSearchForm searchForm,String isMessage)throws ApplicationException {
    DocumentRetrievalManager retrievalManager = new DocumentRetrievalManager(this.sessionContainer, this.conn);
    List systemLogList = new ArrayList();
    try {
// Commented by Ryan Kwan for Performance Tuning 
/*
      List allRelatedUpdateAlertID = (List) getRelatedUpdateAlertIDListByUserID(userID);
      //List allRelatedUpdateAlertID = (List) getRelatedUpdateAlertIDListByUserID(null);
      if (!Utility.isEmpty(allRelatedUpdateAlertID)) {
        systemLogList = (List) getUpdateAlertSystemLogListByUpdateAlertIDList(allRelatedUpdateAlertID, searchForm);
      }
*/
      
      PermissionManager permissionManager = sessionContainer.getPermissionManager();
      List userGroupIDList = Utility.getPropertyList(permissionManager.getUserGroups(), "ID");
      List userRoleIDList = Utility.getPropertyList(permissionManager.getUserRoles(), "ID");
      UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
      if(isMessage.trim().equalsIgnoreCase("yes"))
      {
        ListSystemMessageForm messageform = (ListSystemMessageForm)searchForm;
        String disableActionType = messageform.getDisableActionType();
        String specifyActionType = messageform.getSpecifyActionType();
        systemLogList = alertSystemDAO.getSystemLogListByUserRecordIDGroupIDListRoleIDListForMessage(userID, userGroupIDList, userRoleIDList, searchForm, disableActionType, specifyActionType);
      }else{
      systemLogList = alertSystemDAO.getSystemLogListByUserRecordIDGroupIDListRoleIDList(userID, userGroupIDList, userRoleIDList, searchForm);
      }

    }catch (ApplicationException e){      
      logger.error(e.getMessage());
      throw e;
    }catch (Exception e){
        //should not happen here
    }finally {
      retrievalManager.release();
    }
    return systemLogList;
  }

  //Get Calendar ToDo List by User Recrdd ID
  public List getCalendarToListByUserRecordID (Integer userID, AbstractSearchForm searchForm)throws ApplicationException {
    List systemLogList = new ArrayList();

    try {
      systemLogList = getUpdateAlertCalendarToList();
    }catch (Exception e){
      logger.error(e, e);
    }
    return systemLogList;
  }
  
  //Get Calendar Event List by User Record ID
  public List getCalendarEventListByUserRecordID (Integer userID, AbstractSearchForm searchForm)throws ApplicationException {
    List systemLogList = new ArrayList();

    try {
      systemLogList = getUpdateAlertCalendarEventList();
    }catch (Exception e){
      logger.error(e, e);
    }
    return systemLogList;
  }
  
  //Get Calendar Meeting List by User Record ID
  public List getCalendarMeetingListByUserRecordID (Integer userID, AbstractSearchForm searchForm)throws ApplicationException {
    List systemLogList = new ArrayList();

    try {
      systemLogList = getUpdateAlertCalendarMeetingList();
    }catch (Exception e){
      logger.error(e, e);
    }
    return systemLogList;
  }

  public boolean checkAlertOwner(Integer objectID, Integer curUserID, String alertType) throws ApplicationException {
    boolean existence = false;
    UpdateAlert existUpdateAlert = new UpdateAlert();
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);

    if (UpdateAlert.INVITE_TYPE.equals(alertType)){
      existUpdateAlert=(UpdateAlert)updateAlertDAO.getByObjectTypeObjectIDCreatorID(GlobalConstant.OBJECT_TYPE_DOCUMENT, objectID, curUserID, UpdateAlert.INVITE_TYPE);
    }else{
      existUpdateAlert=(UpdateAlert)updateAlertDAO.getByObjectTypeObjectIDCreatorID(GlobalConstant.OBJECT_TYPE_DOCUMENT, objectID, curUserID);
    }

    if (existUpdateAlert != null && existUpdateAlert.getID()!=null) {
      existence=true;
    }
    updateAlertDAO=null;
    return existence;
  }

  public List getDistinctUserIDListByLists (String[] userIDList, String[] groupIDList, String[] roleIDList) throws ApplicationException {
    List distinctUserIDList = new ArrayList();
    UserRecordDAObject userRecordDAO = new UserRecordDAObject(sessionContainer, conn);
    distinctUserIDList = userRecordDAO.getIDListByLists(Utility.getList(userIDList), Utility.getList(groupIDList), Utility.getList(roleIDList));
    userRecordDAO=null;
    return distinctUserIDList;
  }

  public List getRecipientByUpdateAlertTypeID (Integer updateAlertTypeID, String recipientType) throws ApplicationException {
    List recipient = new ArrayList();
    MtmUpdateAlertRecipientDAObject alertRecipientDAO = new MtmUpdateAlertRecipientDAObject(sessionContainer, conn);
    recipient = alertRecipientDAO.getRecipientListByUpdateAlertTypeIDRecipientType(updateAlertTypeID, recipientType);
    alertRecipientDAO=null;
    return recipient;
  }

  /**
   * @deprecated
   * @param systemLog
   * @param actionType
   * @param actionTypeLevel
   * @param description
   * @throws ApplicationException
   */
  public void createSystemLogAction (UpdateAlertSystemLog systemLog, String actionType, String actionTypeLevel, String description) throws ApplicationException{

    //Check for read status, if already got read record, no need insert new
      //Retrieval the update alert info if null
    if (!checkForSystemLogActionByActionType(systemLog.getID(), UpdateAlertLogAction.READ_ACTION)){
    createSystemLogAction(systemLog.getID(), actionType, description);
    }

  }

  /**
   * @param systemLogID
   * @param actionType
   * @param description
   * @throws ApplicationException
   */
  public void createSystemLogAction(Integer systemLogID, String actionType, String description) 
                                                                          throws ApplicationException {
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(
        sessionContainer, conn);

    UpdateAlertLogAction logAction = new UpdateAlertLogAction();
    logAction.setUpdateAlertSystemLogID(systemLogID);
    UpdateAlertSystemLog systemLog = (UpdateAlertSystemLog) alertSystemDAO
        .getObjectByID(systemLogID);
    logAction.setUpdateAlertID(systemLog.getUpdateAlertID());
    logAction.setUpdateAlertTypeID(systemLog.getUpdateAlertTypeID());
    logAction.setActionType(actionType);
    logAction.setDescription(description);
    logAction.setActorID(sessionContainer.getUserRecordID());
    this.createSystemLogAction(systemLog, logAction);

    alertSystemDAO = null;
  }

  public void createSystemLogAction (UpdateAlertSystemLog systemLog, UpdateAlertLogAction logAction) throws ApplicationException{
    UpdateAlertLogActionDAObject logActionDAO = new UpdateAlertLogActionDAObject(sessionContainer, conn);
    logActionDAO.insertObject(logAction);
    logActionDAO=null;
  }

  public void deleteLogActionBySystemLogID (Integer systemLogID) throws ApplicationException{
    UpdateAlertLogActionDAObject logActionDAO = new UpdateAlertLogActionDAObject(sessionContainer, conn);
    logActionDAO.deleteObjectBySystemLogID(systemLogID);
    logActionDAO=null;
  }
  
  public void deleteLogActionBySystemLogIDCurActor(Integer systemLogID) throws ApplicationException{
     UpdateAlertLogActionDAObject logActionDAO = new UpdateAlertLogActionDAObject(sessionContainer, conn);
     logActionDAO.deleteObjectBySystemLogIDActorID(systemLogID);
     logActionDAO=null;
   }

  public boolean checkForSystemLogActionByActionType (Integer systemLogID, String actionType) throws ApplicationException{
    UpdateAlertLogActionDAObject logActionDAO = new UpdateAlertLogActionDAObject(sessionContainer, conn);
    boolean result  = logActionDAO.getBySystemLogByActionType(systemLogID, actionType);
    logActionDAO=null;
    return result;
  }

  public void newReminderAlert(UpdateAlert updateAlert, String objectType, Integer objectID, AbstractBaseObject obj) throws ApplicationException {

    //get the trigger time; get reminder detail for updateAlert setting
    String alertSubject="";
    String notificationWay="";
    Timestamp targetSrcTime = null;
    Integer versionID = null;
    int reminderAmount = 0;
    String reminderType = "";
    Date triggerTime = null;
    if (GlobalConstant.OBJECT_TYPE_CALENDAR.equals(objectType)) {
      CalendarRecord calendarRecord = (CalendarRecord) ( (CalendarRecord)obj).clone();
//TODO: required defines the notificationWay for Calendar; pls use the new coding version
      notificationWay = calendarRecord.getReminderType();
      targetSrcTime = calendarRecord.getDatetime();
//TODO: required to update if the Calendar structure is change; Also clear up the old code pls
//      reminderType=;
//      reminderAmount = calendarRecord.getReminderAmount().intValue();
      triggerTime = new Date(Utility.addMinute(targetSrcTime, -calendarRecord.getReminderAmount().intValue()).getTime());
    }
    else if (GlobalConstant.OBJECT_TYPE_DOCUMENT.equals(objectType)) {
      DmsDocument dmsDocument = (DmsDocument) ( (DmsDocument)obj).clone();
      notificationWay = TextUtility.join(notificationWay, dmsDocument.getNotificationWay());
      targetSrcTime = Utility.addDay(dmsDocument.getEffectiveEndDate(),1);
      reminderType = dmsDocument.getReminderType();
      reminderAmount = dmsDocument.getReminderAmount().intValue();
      versionID = dmsDocument.getVersionID();
    }

    UpdateAlert newUpdateAlert=this.createUpdateAlert(updateAlert, objectType);

    UpdateAlertType updateAlertType = new UpdateAlertType();
    updateAlertType.setUpdateAlertID(newUpdateAlert.getID());
    updateAlertType.setActionType(UpdateAlert.REMIND_ACTION);
    updateAlertType.setNotifyWay(notificationWay);  
    updateAlertType = createAlertUpdateType(updateAlertType);

    UpdateAlertSystemLog updateAlertSystemLog = new UpdateAlertSystemLog();
    updateAlertSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
    updateAlertSystemLog.setActionUserID(sessionContainer.getUserRecordID());
    updateAlertSystemLog.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
    //updateAlertSystemLog.setRecordStatus(GlobalConstant.STATUS_INACTIVE);
    //fixed follow for calendar
    if (GlobalConstant.OBJECT_TYPE_CALENDAR.equals(objectType)||GlobalConstant.OBJECT_TYPE_DOCUMENT.equals(objectType)){
      updateAlertSystemLog.setRecordStatus(GlobalConstant.STATUS_INACTIVE);     
    }
    updateAlertSystemLog.setActionDate(targetSrcTime);
    updateAlertSystemLog.setVersionID(versionID);
    updateAlertSystemLog = createSystemLog(updateAlertSystemLog);

    MtmUpdateAlertRecipient recipient = new MtmUpdateAlertRecipient();
    recipient.setUpdateAlertID(newUpdateAlert.getID());
    recipient.setRecipientType(UpdateAlert.USER_RECIPIENT);
    recipient.setRecipientID(sessionContainer.getUserRecordID());
    createUpdateAlertRecipient(newUpdateAlert, updateAlertType, recipient);

    //Create Schdule trigger
    List userRecordIDList = new ArrayList(1);
    userRecordIDList.add(sessionContainer.getUserRecordID());
    if (reminderType.indexOf(UpdateAlert.MINUTE)>=0) {
      triggerTime = new Date(Utility.addMinute(targetSrcTime, -reminderAmount).getTime());
    }
    else if (reminderType.indexOf(UpdateAlert.HOUR)>=0) {
      triggerTime = new Date(Utility.addHour(targetSrcTime, -reminderAmount).getTime());
    }
    else if (reminderType.indexOf(UpdateAlert.DAY)>=0) {
      triggerTime = new Date(Utility.addDay(targetSrcTime, -reminderAmount).getTime());
    }
    else if (reminderType.indexOf(UpdateAlert.WEEK)>=0) {
      triggerTime = new Date(this.addWeek(targetSrcTime, -reminderAmount).getTime());
    }    
    else if (reminderType.indexOf(UpdateAlert.MONTH)>=0) {
      triggerTime = new Date(Utility.addMonth(targetSrcTime, -reminderAmount).getTime());
    }
    else if (reminderType.indexOf(UpdateAlert.YEAR)>=0) {
      triggerTime = new Date(Utility.addYear(targetSrcTime, -reminderAmount).getTime());
    }

    //To schedule the reminder job
    scheduleJobNotification(newUpdateAlert, updateAlertType,
                            obj, triggerTime,
                            userRecordIDList,
                            updateAlertSystemLog.getID(), TextUtility.formatTimestamp(targetSrcTime));
   }


   /**
    * updateReminderAlert
    *
    * Update ReminderAlert record  this method for document
    *
    * @param objectType
    * @param objectID
    * @param obj
    * @throws ApplicationException
    */
   public void updateReminderAlert(String objectType, Integer objectID, AbstractBaseObject obj) throws ApplicationException {

     //get the trigger time; get reminder detail for updateAlert setting
     String notificationWay="";
     Timestamp targetSrcTime = null;
     Integer versionID = null;
     int reminderAmount = 0;
     String reminderType = "";
     Date triggerTime = null;
     DmsDocument dmsDocument = null;
     CalendarRecord calendarRecord = null;
     if (GlobalConstant.OBJECT_TYPE_CALENDAR.equals(objectType)) {
       calendarRecord = (CalendarRecord) ( (CalendarRecord)obj).clone();
       //TODO: required defines the notificationWay for Calendar; pls use the new coding version
       notificationWay = calendarRecord.getReminderType();
       targetSrcTime = calendarRecord.getDatetime();
       //TODO: required to update if the Calendar structure is change; Also clear up the old code pls
       //      reminderType=;
       //      reminderAmount = calendarRecord.getReminderAmount().intValue();
       triggerTime = new Date(Utility.addMinute(targetSrcTime, -calendarRecord.getReminderAmount().intValue()).getTime());
     }
     else if (GlobalConstant.OBJECT_TYPE_DOCUMENT.equals(objectType)) {
       dmsDocument = (DmsDocument) ( (DmsDocument)obj).clone();
       notificationWay = TextUtility.join(notificationWay, dmsDocument.getNotificationWay());
       targetSrcTime = Utility.addDay(dmsDocument.getEffectiveEndDate(),1);
 //      targetSrcTime = dmsDocument.getEffectiveEndDate();
       reminderType = dmsDocument.getReminderType();
       if (dmsDocument.getReminderAmount()!=null) {
        reminderAmount = dmsDocument.getReminderAmount().intValue();
      }
       versionID = dmsDocument.getVersionID();
     }
     UpdateAlert updateAlert = this.getUpdateAlertByObjectTypeObjectID(objectType, objectID);
     if(Utility.isEmpty(updateAlert)){
       UpdateAlert newUpdateAlert = new UpdateAlert();
       if (GlobalConstant.OBJECT_TYPE_CALENDAR.equals(objectType)) {
         newUpdateAlert.setObjectType(UpdateAlert.CALENDAR_TYPE);
         newUpdateAlert.setObjectID(dmsDocument.getID());
       }else if(GlobalConstant.OBJECT_TYPE_DOCUMENT.equals(objectType)){
         newUpdateAlert.setObjectType(UpdateAlert.DOCUMENT_TYPE);
         newUpdateAlert.setObjectID(dmsDocument.getID());
       }  
       updateAlert = this.createUpdateAlert(newUpdateAlert, objectType);
     }
     if (updateAlert!=null) {
       delScheduleJobNotification(updateAlert);
       UpdateAlertType updateAlertType = this.getUpdateAlertTypeByActionTypeUpdateAlertID(UpdateAlert.REMIND_ACTION, updateAlert.getID());
       UpdateAlertSystemLog updateAlertSystemLog = null;
       if(Utility.isEmpty(updateAlertType)){
    	    updateAlertType = new UpdateAlertType();
    	    updateAlertType.setUpdateAlertID(updateAlert.getID());
    	    updateAlertType.setActionType(UpdateAlert.REMIND_ACTION);
    	    updateAlertType.setNotifyWay(notificationWay);
    	    updateAlertType = createAlertUpdateType(updateAlertType);

    	    updateAlertSystemLog = new UpdateAlertSystemLog();
    	    updateAlertSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
    	    updateAlertSystemLog.setActionUserID(sessionContainer.getUserRecordID());
    	    updateAlertSystemLog.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
    	    //updateAlertSystemLog.setRecordStatus(GlobalConstant.STATUS_INACTIVE);
    	    //fixed follow for calendar
    	    if (GlobalConstant.OBJECT_TYPE_CALENDAR.equals(objectType)||GlobalConstant.OBJECT_TYPE_DOCUMENT.equals(objectType)){
    	      updateAlertSystemLog.setRecordStatus(GlobalConstant.STATUS_INACTIVE);     
    	    }
    	    updateAlertSystemLog.setActionDate(targetSrcTime);
    	    updateAlertSystemLog.setVersionID(versionID);
    	    updateAlertSystemLog = createSystemLog(updateAlertSystemLog);

    	    MtmUpdateAlertRecipient recipient = new MtmUpdateAlertRecipient();
    	    recipient.setUpdateAlertID(updateAlert.getID());
    	    recipient.setRecipientType(UpdateAlert.USER_RECIPIENT);
    	    recipient.setRecipientID(sessionContainer.getUserRecordID());
    	    createUpdateAlertRecipient(updateAlert, updateAlertType, recipient);
       }else{
    	   //   UpdateAlertType updateAlertType   =  updateAlertType = (UpdateAlertType)this.getUpdateAlertTypeByActionTypeUpdateAlertID(UpdateAlert.INVITE_ACTION, updateAlert.getID());
           updateAlertType.setNotifyWay(notificationWay);
           updateAlertType = this.updateUpdateAlertType(updateAlertType);           
           updateAlertSystemLog = this.getSystemLogByUpdateAlertTypeIDActionUserID(updateAlertType.getID(),
             sessionContainer.getUserRecordID());
           if (Utility.isEmpty(updateAlertSystemLog)) {
             updateAlertSystemLog = new UpdateAlertSystemLog();
             updateAlertSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
             updateAlertSystemLog.setActionUserID(sessionContainer.getUserRecordID());
           }
           if (GlobalConstant.OBJECT_TYPE_CALENDAR.equals(objectType)) {
             calendarRecord = (CalendarRecord) ( (CalendarRecord)obj).clone();
             if (calendarRecord.getReminderType().indexOf(UpdateAlert.SYSTEM_NOTIFICATION) < 0) {
               updateAlertSystemLog.setRecordStatus(GlobalConstant.STATUS_INACTIVE);
             }
           }else {
             updateAlertSystemLog.setRecordStatus(GlobalConstant.STATUS_INACTIVE);
           }
           updateAlertSystemLog.setActionDate(targetSrcTime);
           updateAlertSystemLog.setVersionID(versionID);
           //updateAlertSystemLog = (UpdateAlertSystemLog)this.updateSystemLog(updateAlertSystemLog);
           updateAlertSystemLog = createSystemLog(updateAlertSystemLog);//barbin EIP-1474  
       }
       //Create Schdule trigger
       List userRecordIDList = new ArrayList(1);
       userRecordIDList.add(sessionContainer.getUserRecordID());
       if (reminderType.indexOf(UpdateAlert.MINUTE) >= 0) {
         triggerTime = new Date(Utility.addMinute(targetSrcTime, -reminderAmount).getTime());
       }
       else if (reminderType.indexOf(UpdateAlert.HOUR) >= 0) {
         triggerTime = new Date(Utility.addHour(targetSrcTime, -reminderAmount).getTime());
       }
       else if (reminderType.indexOf(UpdateAlert.DAY) >= 0) {
         triggerTime = new Date(Utility.addDay(targetSrcTime, -reminderAmount).getTime());
       }
       else if (reminderType.indexOf(UpdateAlert.WEEK)>=0) {//barbin EIP-1474
    	 triggerTime = new Date(this.addWeek(targetSrcTime, -reminderAmount).getTime());
       } 
       else if (reminderType.indexOf(UpdateAlert.MONTH) >= 0) {
         triggerTime = new Date(Utility.addMonth(targetSrcTime, -reminderAmount).getTime());
       }
       else if (reminderType.indexOf(UpdateAlert.YEAR) >= 0) {
         triggerTime = new Date(Utility.addYear(targetSrcTime, -reminderAmount).getTime());
       }

       //To schedule the reminder job
       scheduleJobNotification(updateAlert, updateAlertType,
                               obj, triggerTime,
                               userRecordIDList,
                               updateAlertSystemLog.getID(), TextUtility.formatTimestamp(targetSrcTime));
     }

    }


    /**
     * updateReminderAlert
     *
     * Update ReminderAlert record  this method for calendar
     *
     * @param objectType
     * @param objectID
     * @param obj
     * @param calendarRecordEventType
     * @throws ApplicationException
     */
    public void updateReminderAlert(String objectType, Integer objectID, AbstractBaseObject obj,String calendarRecordEventType) throws ApplicationException {

      //get the trigger time; get reminder detail for updateAlert setting
      String notificationWay="";
      Timestamp targetSrcTime = null;
      Integer versionID = null;
      int reminderAmount = 0;
      String reminderType = "";
      Date triggerTime = null;
      if (GlobalConstant.OBJECT_TYPE_CALENDAR.equals(objectType)) {
        CalendarRecord calendarRecord = (CalendarRecord) ( (CalendarRecord)obj).clone();
        //TODO: required defines the notificationWay for Calendar; pls use the new coding version
        notificationWay = calendarRecord.getReminderType();
        targetSrcTime = calendarRecord.getDatetime();
        //TODO: required to update if the Calendar structure is change; Also clear up the old code pls
        //      reminderType=;
        //      reminderAmount = calendarRecord.getReminderAmount().intValue();
        triggerTime = new Date(Utility.addMinute(targetSrcTime, -calendarRecord.getReminderAmount().intValue()).getTime());
      }
      else if (GlobalConstant.OBJECT_TYPE_DOCUMENT.equals(objectType)) {
        DmsDocument dmsDocument = (DmsDocument) ( (DmsDocument)obj).clone();
        notificationWay = TextUtility.join(notificationWay, dmsDocument.getNotificationWay());
        targetSrcTime = Utility.addDay(dmsDocument.getEffectiveEndDate(),1);
 //       targetSrcTime = dmsDocument.getEffectiveEndDate();
        reminderType = dmsDocument.getReminderType();
        reminderAmount = dmsDocument.getReminderAmount().intValue();
        versionID = dmsDocument.getVersionID();
      }
      UpdateAlert updateAlert = this.getUpdateAlertByObjectTypeObjectID(objectType, objectID);
      delScheduleJobNotification(updateAlert);
      UpdateAlertType updateAlertType  = null;
      if (calendarRecordEventType.equals(CalendarRecord.EVENT_TYPE_CALENDAR_MEETING) ){
        updateAlertType = this.getUpdateAlertTypeByActionTypeUpdateAlertID(UpdateAlert.INVITE_ACTION, updateAlert.getID());
      }else{
        updateAlertType = this.
            getUpdateAlertTypeByActionTypeUpdateAlertID(UpdateAlert.REMIND_ACTION,
            updateAlert.getID());
      }
      updateAlertType.setNotifyWay(notificationWay);
      updateAlertType = this.updateUpdateAlertType(updateAlertType);
      UpdateAlertSystemLog updateAlertSystemLog = this.getSystemLogByUpdateAlertTypeIDActionUserID(updateAlertType.getID(), sessionContainer.getUserRecordID());
      if (GlobalConstant.OBJECT_TYPE_CALENDAR.equals(objectType) ) {
        CalendarRecord calendarRecord = (CalendarRecord) ( (CalendarRecord)obj).clone();
        if (calendarRecord.getReminderType().indexOf(UpdateAlert.SYSTEM_NOTIFICATION) < 0) {
          updateAlertSystemLog.setRecordStatus(GlobalConstant.STATUS_INACTIVE);
        }
      } else {
        updateAlertSystemLog.setRecordStatus(GlobalConstant.STATUS_INACTIVE);
      }
      updateAlertSystemLog.setActionDate(targetSrcTime);
      updateAlertSystemLog.setVersionID(versionID);
     // updateAlertSystemLog = (UpdateAlertSystemLog) this.updateSystemLog(updateAlertSystemLog);
      updateAlertSystemLog = createSystemLog(updateAlertSystemLog);// barbin EIP-1474

      //Create Schdule trigger
      List userRecordIDList = new ArrayList(1);
      userRecordIDList.add(sessionContainer.getUserRecordID());
      if (reminderType.indexOf(UpdateAlert.MINUTE)>=0) {
        triggerTime = new Date(Utility.addMinute(targetSrcTime, -reminderAmount).getTime());
      }
      else if (reminderType.indexOf(UpdateAlert.HOUR)>=0) {
        triggerTime = new Date(Utility.addHour(targetSrcTime, -reminderAmount).getTime());
      }
      else if (reminderType.indexOf(UpdateAlert.DAY)>=0) {
        triggerTime = new Date(Utility.addDay(targetSrcTime, -reminderAmount).getTime());
      }
      else if (reminderType.indexOf(UpdateAlert.WEEK)>=0) {//barbin EIP-1474
     	triggerTime = new Date(this.addWeek(targetSrcTime, -reminderAmount).getTime());
      } 
      else if (reminderType.indexOf(UpdateAlert.MONTH)>=0) {
        triggerTime = new Date(Utility.addMonth(targetSrcTime, -reminderAmount).getTime());
      }
      else if (reminderType.indexOf(UpdateAlert.YEAR)>=0) {
        triggerTime = new Date(Utility.addYear(targetSrcTime, -reminderAmount).getTime());
      }

      //To schedule the reminder job
      scheduleJobNotification(updateAlert, updateAlertType,
                              obj, triggerTime,
                              userRecordIDList,
                              updateAlertSystemLog.getID(), TextUtility.formatTimestamp(targetSrcTime));

     }

/**********************************************************
 Update the read operation log by passing the systemLogID
************************************************************/


  public void updateReadOperationLog(Integer systemLogID) throws ApplicationException{
   if (systemLogID!=null) {
     if (this.checkForSystemLogActionByActionType(systemLogID, UpdateAlertLogAction.READ_ACTION)) {
       //Got READ record; Can go delete the READ reocrd to mark as un-read
       //this.deleteLogActionBySystemLogID(systemLogID);
     }
     else {
       //Go create read record
       UpdateAlertSystemLog systemLog = new UpdateAlertSystemLog();
       systemLog.setID(systemLogID);
       this.createSystemLogAction(systemLog, UpdateAlertLogAction.READ_ACTION, null, null);
     }
   }
   try {
     conn.commit();
   } catch (Exception e) {

     throw new ApplicationException(ErrorConstant.DB_COMMIT_ERROR, e);
   }


 }

  public UpdateAlert createMultiUpdateAlert(String objectID,String documentType,UpdateAlertType[] updateTypes, MtmUpdateAlertRecipient[] updateRecipient, Integer versionID, String objectName, Timestamp refDate, String eventName, Integer creatorID, List notifyUserIDList) throws ApplicationException {
    //check main update alert record exists for new creation
    UpdateAlert newupdateAlert = new UpdateAlert();
    try{
      UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
      String [] documentID = TextUtility.splitString(objectID,",");
      for(int i=0;i<documentID.length;i++){
        newupdateAlert = (UpdateAlert) updateAlertDAO.getByObjectTypeObjectID(GlobalConstant.OBJECT_TYPE_DOCUMENT, TextUtility.parseIntegerObj(documentID[i]));
      }
      createMultiInviteTypesRecipientsNLogs(objectID, documentType,updateTypes, updateRecipient, versionID, objectName, refDate, eventName, creatorID, notifyUserIDList);
      updateAlertDAO = null;
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      logger.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
    }
    return newupdateAlert;
  }
  
  public void createMultiInviteTypesRecipientsNLogs(String objectID,String documentType,UpdateAlertType[] updateTypes, MtmUpdateAlertRecipient[] updateRecipient, Integer versionID, String objectName, Timestamp refDate, String eventName, Integer creatorID, List notifyUserIDList) throws ApplicationException {
    NotificationAdapter na = new NotificationAdapter(sessionContainer, conn);
    UpdateAlertTypeDAObject updateTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    MtmUpdateAlertRecipientDAObject alertRecipientDAO = new MtmUpdateAlertRecipientDAObject(sessionContainer, conn);
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    ApplicationExceptionList exceptionList = new ApplicationExceptionList();
    UpdateAlertTypeDAObject updateAlertTypeDAO = new UpdateAlertTypeDAObject(sessionContainer, conn);
    String [] documentID = TextUtility.splitString(objectID,",");
    UpdateAlert updateAlert=new UpdateAlert();
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    String nActionType="";
    String notifyWay="";
    Integer systemLogID = null;
    try{
      for (int i = 0; i < updateTypes.length; i++) {
        UpdateAlertType updateAlertType = updateTypes[i];
        nActionType=updateAlertType.getActionType();
        //for(int n=0;n<documentID.length;n++){
          updateAlert = (UpdateAlert) updateAlertDAO.getByObjectTypeObjectID(GlobalConstant.OBJECT_TYPE_DOCUMENT, TextUtility.parseIntegerObj(documentID[i]));
          updateAlertType.setUpdateAlertID(updateAlert.getID());
        for (int r = 0; r < updateRecipient.length; r++) {
          MtmUpdateAlertRecipient recipient = updateRecipient[r];
          recipient.setUpdateAlertID(updateAlert.getID());
          recipient.setUpdateAlertTypeID(updateAlertType.getID());
          alertRecipientDAO.insertObject(recipient);
        }
        //}
        StringTokenizer stoken = new StringTokenizer(updateAlertType.getNotifyWay(), ",");
        notifyWay=updateAlertType.getNotifyWay();
        while (stoken.hasMoreElements()) {
          String actionType = (String) stoken.nextElement();
          if (UpdateAlert.EMAIL_NOTIFICATION.equals(actionType)) {
            if (updateAlertType.getNotifyWay().indexOf(UpdateAlert.SYSTEM_NOTIFICATION) < 0) {
              if (UpdateAlert.INVITE_ACTION.equals(updateAlertType.getActionType())
                    //* for workflow action alert START
                    || UpdateAlert.NOTIFY_TASK_COMPLETED_ACTION.equals(updateAlertType.getActionType())
                    || UpdateAlert.NOTIFY_TASK_ARRIVED_ACTION.equals(updateAlertType.getActionType())
                    || UpdateAlert.NOTIFY_TASK_OWNER_OVERDUE_ACTION.equals(updateAlertType.getActionType())
                    || UpdateAlert.NOTIFY_TASK_ALL_OVERDUE_ACTION.equals(updateAlertType.getActionType())
                    || UpdateAlert.NOTIFY_STOP_TRACK.equals(updateAlertType.getActionType())
                    || UpdateAlert.DELEGATION_ACTION.equals(updateAlertType.getActionType())
                    || UpdateAlert.NOTIFY_DELEGATION_USER.equals(updateAlertType.getActionType())
                    || UpdateAlert.DISCUSS_ACTION.equals(updateAlertType.getActionType())
                    //* for workflow action alert END
                 ) {
              
                //Active the System Log
                UpdateAlertSystemLog alertSystemLog = new UpdateAlertSystemLog();
                alertSystemLog.setActionUserID(sessionContainer.getUserRecordID());
                alertSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
                alertSystemLog.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
                alertSystemLog.setVersionID(versionID);
                alertSystemLog = (UpdateAlertSystemLog) alertSystemDAO.insertObject(alertSystemLog);
                
              }
            }
          }
          else if (UpdateAlert.SYSTEM_NOTIFICATION.equals(actionType)) {
            if (UpdateAlert.INVITE_ACTION.equals(updateAlertType.getActionType())
                    //* for workflow action alert START
                    || UpdateAlert.NOTIFY_TASK_COMPLETED_ACTION.equals(updateAlertType.getActionType())
                    || UpdateAlert.NOTIFY_TASK_ARRIVED_ACTION.equals(updateAlertType.getActionType())
                    || UpdateAlert.NOTIFY_TASK_OWNER_OVERDUE_ACTION.equals(updateAlertType.getActionType())
                    || UpdateAlert.NOTIFY_TASK_ALL_OVERDUE_ACTION.equals(updateAlertType.getActionType())
                    || UpdateAlert.NOTIFY_STOP_TRACK.equals(updateAlertType.getActionType())
                    || UpdateAlert.DELEGATION_ACTION.equals(updateAlertType.getActionType())
                    || UpdateAlert.NOTIFY_DELEGATION_USER.equals(updateAlertType.getActionType())
                    || UpdateAlert.DISCUSS_ACTION.equals(updateAlertType.getActionType())
                    //* for workflow action alert END
               ) {
            
              //Active the System Log
                 UpdateAlertSystemLog alertSystemLog = new UpdateAlertSystemLog();
                 alertSystemLog.setActionUserID(sessionContainer.getUserRecordID());
                 alertSystemLog.setUpdateAlertTypeID(updateAlertType.getID());
                 alertSystemLog.setRecordStatus(GlobalConstant.STATUS_ACTIVE);
                 alertSystemLog.setActionDate(refDate);
                 alertSystemLog.setVersionID(versionID);
                 alertSystemLog = (UpdateAlertSystemLog) alertSystemDAO.insertObject(alertSystemLog);
                 if(alertSystemLog!=null){
                    systemLogID = alertSystemLog.getID();      
                  }
            }
          }
        }
      }
      String[]nNotifyWay=TextUtility.splitString(notifyWay,",");
      //Active the Email Alert
      for(int i=0;i<nNotifyWay.length;i++){
        if (UpdateAlert.EMAIL_NOTIFICATION.equals(nNotifyWay[i])) {
         try {
            na.multiNotifyByEmailInvite(updateAlert.getObjectType(),objectID,nActionType,
                               updateRecipient, objectName, refDate,
                               eventName, creatorID, notifyUserIDList,false,systemLogID);
         } catch (ApplicationException appEx) { // in case cannot send email and exception is thrown 
         logger.info("Cannot send invitation email.");
         exceptionList.addException(appEx);
        }
       }
      }
      conn.commit();
      updateTypeDAO = null;
      alertRecipientDAO = null;
      alertSystemDAO = null;
      na.release();
    } catch (ApplicationException appEx) {
      logger.error(appEx, appEx);
    } catch (Exception e) {
      logger.error(e, e);
    }
  }
  public UpdateAlert updateMultiUpdateAlert(String objectID,String documentType, UpdateAlertType[] updateTypes, MtmUpdateAlertRecipient[] updateRecipient, Integer versionID, String objectName, Timestamp refDate, String eventName, Integer creatorID, List notifyUserIDList) throws ApplicationException {
    UpdateAlertDAObject updateAlertDAO = new UpdateAlertDAObject(sessionContainer, conn);
    UpdateAlert updateAlert = new UpdateAlert();
    UpdateAlert newUpdateAlert = new UpdateAlert();
    try {
         /*String [] documentID = TextUtility.splitString(objectID,",");
         for(int i=0;i<documentID.length;i++){
           updateAlert = (UpdateAlert) updateAlertDAO.getByObjectTypeObjectID(GlobalConstant.OBJECT_TYPE_DOCUMENT, TextUtility.parseIntegerObj(documentID[i]));
           newUpdateAlert = (UpdateAlert) updateAlertDAO.updateObject(updateAlert);
           deleteUpdateAlert(updateAlert, false);
         }*/
         createMultiInviteTypesRecipientsNLogs(objectID, documentType, updateTypes, updateRecipient, versionID, objectName, refDate, eventName, creatorID, notifyUserIDList);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      logger.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, e);
    }
    return newUpdateAlert;
  }
  
  public UpdateAlertSystemLog getOldAlertSystemLog(List alertTypeList,String actionType) throws ApplicationException{
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    for(int i=0;i<alertTypeList.size();i++){
      UpdateAlertType updateAlertType=(UpdateAlertType)alertTypeList.get(i);
      UpdateAlertSystemLog alertSystemLog=(UpdateAlertSystemLog)alertSystemDAO.getByUpdateAlertTypeIDActionUserID(updateAlertType.getID(),sessionContainer.getUserRecordID());
      if(!Utility.isEmpty(alertSystemLog)){
        if(actionType.equals(updateAlertType.getActionType())){
          return alertSystemLog;
        }
      }
    }
    return null;
  }
  
  public List getListOldAlertSystemLog(UpdateAlertType updateAlertType,String actionType) throws ApplicationException{
  	List result = new ArrayList();
  	List updateAlertList = null;
    UpdateAlertSystemLogDAObject alertSystemDAO = new UpdateAlertSystemLogDAObject(sessionContainer, conn);
    updateAlertList = alertSystemDAO.getListByUpdateAlertTypeIDActionUserID(updateAlertType.getID(),sessionContainer.getUserRecordID());
      
    if (updateAlertList == null) return null;
    for (int k=0;k < updateAlertList.size();k++){
    	UpdateAlertSystemLog alertSystemLog = (UpdateAlertSystemLog)updateAlertList.get(k);
    	if(!Utility.isEmpty(alertSystemLog)){
        if(actionType.equals(updateAlertType.getActionType())){
          result.add(alertSystemLog);
        }
      }
    }
    return result;
  }
  
  /**
   * Returns Calendar converted from Timestamp.
   *
   * @param   inTime Source timestamp which to be converted.
   * @return  Calendar object which converted from input.
   */
  public static java.util.Calendar timestampToCalendar(java.sql.Timestamp inTime) {
    if (inTime == null) {
      return (null);
    }
    java.util.Calendar cal = java.util.Calendar.getInstance();
    cal.setTime(inTime);
    return (cal);
  }
  
  public static java.sql.Timestamp calendarToTimestamp(java.util.Calendar inCal) {
    if (inCal == null) {
      return (null);
    }
    java.sql.Timestamp time = new java.sql.Timestamp(inCal.getTime().getTime());
    return (time);
  }
  
  /**
   * addWeek - Returns the timestamp after adding certain amount of day.
   *
   * @param   src Source timestamp.
   * @param   val Number of hours going to add, can be negative number.
   * @return  Timestamp after adding certain amount of hours.
   */
  public static java.sql.Timestamp addWeek(java.sql.Timestamp src, int val) {
    java.util.Calendar tmpCal = timestampToCalendar(src);
    if (tmpCal == null) {
      return(null);
    }
    tmpCal.add(java.util.Calendar.WEEK_OF_MONTH, val);
    return (calendarToTimestamp(tmpCal));
  }

  public List getExternalEmailByRecipientIDList(List externalEmailList) {
    List emailList = new ArrayList();
    ContactPersonDAObject contactPersonDAObject = new ContactPersonDAObject(sessionContainer,conn);
      ContactPerson contactPerson = new ContactPerson();
      for(int i=0;i<externalEmailList.size();i++){
      try {
        contactPerson=(ContactPerson)contactPersonDAObject.getObjectByID((Integer)externalEmailList.get(i));
        emailList.add(contactPerson.getEmail());
      }
      catch (ApplicationException e) {
        logger.error(e, e);
      }
      }
    return emailList;
  }
}